Cloud FunctionsでGoogle Cloud Python Loggingライブラリを使ってみる(初心者向け)
データアナリティクス事業本部、池田です。
少し前にGoogle CloudのLoggingのPythonライブラリに関するアップデートがありました。
【 Getting Started with Google Cloud Logging Python v3.0.0 】
記事によると、Cloud Functionsなどでログのドロップが起きにくくなったようです。
これまであまりきちんとしたログ実装をしていなかったので、この機会に使い方を調べてみました。
ライブラリをローカルから使ってみる
Google Cloud Python logging libraryは、Google Cloudのサービス上に限らず、 ローカルからでもログを送ることができるようなので、まずローカル(Python 3.7.7)で試してみました。
import google.cloud.logging client = google.cloud.logging.Client() client.setup_logging() import logging logging.warning("Hello World")
上記の内容のPythonファイルを作成し、
export GOOGLE_APPLICATION_CREDENTIALS="{credentialファイルのパス}"
のように認証情報を環境変数に設定して実行すると、↓Google Cloudプロジェクトへログが送信されていました。
warningの黄色いアイコンになっています。
※ Cloud Shell からであれば認証情報のexportは不要でした
Cloud FunctionsでのLogging
今回は、Pub/Subに紐づくCloud Functionsを実装し、 print()での出力とライブラリでのログ出力をやってみました。
(以降ではCloud Shell上でのコマンド発行を前提としています。)
Pub/Subトピックの作成
メッセージの送受信のために、
Pub/Sub のトピックを
sample_logging_topic
という名前で作成しました。
gcloud pubsub topics create sample_logging_topic
print()する関数を作成
比較用に標準のprint()関数で出力をするCloud Functionsの関数を作成してみます。
import base64 import os import json def sample_print_fn(event, context): pubsub_message = base64.b64decode(event["data"]).decode("utf-8") print(f"pubsub_message: {pubsub_message}") print(json.dumps(event)) print(event) print(f"env: {os.getenv('ENV_VAR')}") try: print("print at try") _ = 1 / 0 except Exception: print("print at except") raise finally: print("print at finally")
内容としては、関数のパラメータ( event["data"]
)や環境変数( os.getenv('ENV_VAR')
)を
print()しています。最後にゼロ除算で例外を起こしています。
上記のファイルを以下のコマンドで sample_print_fn
という関数名でデプロイします。
gcloud functions deploy sample_print_fn \ --region asia-northeast1 \ --runtime python39 \ --trigger-topic sample_logging_topic \ --timeout 30 \ --memory 128MB \ --set-env-vars ENV_VAR=環境変数からの値
( --entry-point
を指定していないので、関数名のsample_print_fnが実行されます。)
ライブラリを利用する関数を作成
ライブラリを使用するパターンのコードが以下です。
import base64 import os import json from logging import getLogger, DEBUG import google.cloud.logging logging_client = google.cloud.logging.Client() logging_client.setup_logging() logger = getLogger(__name__) logger.setLevel(DEBUG) def sample_logging_fn(event, context): pubsub_message = base64.b64decode(event["data"]).decode("utf-8") logger.info(f"pubsub_message: {pubsub_message}") logger.debug(json.dumps(event)) logger.debug(event) logger.warning(f"env: {os.getenv('ENV_VAR')}") try: logger.info("info at try") _ = 1 / 0 except Exception: logger.error("error at except") raise finally: logger.debug("debug at finally")
Python標準のloggingライブラリと連携して使うことが推奨のようです。
ログレベルを設定しない( logger.setLevel(DEBUG)
が無い)場合は、info()はログ出力されてdebug()は出力されませんでした。
コンソールのログ エクスプローラなどで参照する時にもフィルタができるので、細かいログレベルで出力してしまって良いかなと思いました。
ライブラリを利用できるように 依存関係を別ファイルに記述 します。
google.cloud.logging>=3.0.0
あとは、同様に sample_logging_fn
という関数名でデプロイします。
gcloud functions deploy sample_logging_fn \ --region asia-northeast1 \ --runtime python39 \ --trigger-topic sample_logging_topic \ --timeout 30 \ --memory 128MB \ --set-env-vars ENV_VAR=環境変数からの値
メッセージの発行~ログ確認
Pub/Subにメッセージを発行して、関数を動作させてログを確認してみます。
gcloud pubsub topics publish sample_logging_topic --message="pubsubのメッセージ"
↓print()のパターンのログ(Cloud Functionsの「ログ」タブ)。
コンソール上の「重大度」は「デフォルト」として扱われます。
↓ライブラリを使ったパターンのログ。
ログレベルが設定されていることがアイコンからも分かります。
↓ログ エクスプローラで見た場合。
ちなみに logger.debug(json.dumps(event))
でも logger.debug(event)
でも、ログ上は違いは見受けられませんでした。
おわりに
ログは奥が深いので、ハンドラなどの使い方にも慣れたらブログにしたいと思います。たぶん。